package com.spa.interfaces.member;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.UUID;
import com.spa.application.command.member.*;
import com.spa.application.dto.PageResult;
import com.spa.application.dto.member.*;
import com.spa.application.dto.wx.WXPayDTO;
import com.spa.application.query.member.*;
import com.spa.application.service.member.MemberMassagistApplicationService;
import com.spa.application.service.member.MemberMyApplicationService;
import com.spa.application.service.member.MemberOrderApplicationService;
import com.spa.infrastructure.annotation.RepeatSubmit;
import com.spa.infrastructure.common.CommonCode;
import com.spa.infrastructure.common.ResponseMessage;
import com.spa.infrastructure.enums.dict.massagist.MassagistStatusEnum;
import com.spa.infrastructure.exception.SpaException;
import com.spa.infrastructure.util.RedisUtil;
import com.spa.interfaces.BaseController;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("member/order")
@Slf4j
public class MemberOrderController extends BaseController {

    @Resource
    private MemberOrderApplicationService memberOrderApplicationService;

    @Resource
    private MemberMyApplicationService memberMyApplicationService;

    @Resource
    private MemberMassagistApplicationService memberMassagistApplicationService;

    @Resource
    private RedisUtil redisUtil;

    @PostMapping("/enterPrecontract")
    public ResponseMessage<MemberOrderPrecontractDTO> enterPrecontract(@Validated @RequestBody MemberEnterOrderPrecontractCommand command) {
        if (!StpUtil.isLogin()){
            return responseHelper.fail(CommonCode.UN_LOGIN);
        }
        memberOrderApplicationService.precheckPrecontract(command);
        return responseHelper.success();
    }

    @PostMapping("/precontract")
    public ResponseMessage<MemberOrderPrecontractDTO> precontract(@Validated @RequestBody MemberOrderPrecontractCommand command) {
        return responseHelper.success(memberOrderApplicationService.precontract(command));
    }

    @PostMapping("/addOrder")
    public ResponseMessage<MemberOrderDTO> addOrder(@Validated @RequestBody MemberOrderAddCommand command) {
        String lockKey = "massagistIdLock:" + command.getMassagistId();
        String id = UUID.fastUUID().toString(true);
        try {
            boolean lockFlag = redisUtil.getLock(lockKey, id);
            if (!lockFlag) {
                throw new SpaException("该技师重复接单");
            }
            return responseHelper.success(memberOrderApplicationService.addOrder(command));
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new SpaException("该时间段已经被预约！");
        } finally {
            redisUtil.releaseLock(lockKey, id);
        }
    }

    @PostMapping("/extraTime")
    public ResponseMessage<MemberOrderExtDTO> extraTime(@Validated @RequestBody MemberOrderExtAddCommand command) {
        return responseHelper.success(memberOrderApplicationService.addOrderExt(command));
    }

    @PostMapping("/cancel")
    public ResponseMessage cancel(@Validated @RequestBody OrderCancelCommand command) {
        if (memberOrderApplicationService.cancelOrder(command)){
            return responseHelper.success();
        }
        return responseHelper.fail();
    }

    @PostMapping("/pay")
    public ResponseMessage<WXPayDTO> pay(@RequestBody OrderPayCommand command) throws NoSuchAlgorithmException, InvalidKeySpecException {
        return responseHelper.success(memberOrderApplicationService.pay(command));
    }

    @PostMapping("/extPay")
    public ResponseMessage<WXPayDTO> extPay(@RequestBody OrderExtPayCommand command) throws NoSuchAlgorithmException, InvalidKeySpecException {
        return responseHelper.success(memberOrderApplicationService.extPay(command));
    }

    /**
     * 订单-分页获取订单
     * @param query
     * @return
     */
    @PostMapping("/page")
    @SaIgnore
    public ResponseMessage<PageResult<MemberOrderDTO>> page(@RequestBody MemberOrderQuery query) {
        if (!StpUtil.isLogin()) {
            PageResult<MemberOrderDTO> pageDto = new PageResult<>();
            return responseHelper.success(pageDto);
        }
        return responseHelper.success(memberOrderApplicationService.page(query));
    }

    @PostMapping("/details")
    public ResponseMessage<MemberOrderDetailDTO> details(@Validated @RequestBody MemberOrderDetailsQuery query) {
        return responseHelper.success(memberOrderApplicationService.detail(query));
    }

    @PostMapping("/ticket/queryMyUsableTicketList")
    public ResponseMessage<List<MemberTicketDTO>> queryMyUsableTicketList(@Validated @RequestBody MemberCouponQuery query) {
        return responseHelper.success(memberMyApplicationService.couponUsableMyList(query));
    }

    @PostMapping("/queryMassagistTime")
    public ResponseMessage<MemberAppointmentTimeDTO> queryMassagistTime(@Validated @RequestBody MemberMassagistTimeQuery query) {
        return responseHelper.success(memberOrderApplicationService.appointmentTime(query));
    }

    @PostMapping("/allowMassagistPage")
    public ResponseMessage<PageResult<MemberMassagistDTO>> allowMassagistPage(@Validated @RequestBody MemberMassagistQuery query) {
        List<Integer> inStatus = new ArrayList<>();
        inStatus.add(MassagistStatusEnum.$20.getCode());
        inStatus.add(MassagistStatusEnum.$30.getCode());
        query.setInStatus(inStatus);
        return responseHelper.success(memberMassagistApplicationService.page(query));
    }

    @PostMapping("/massagistEvaluate")
    @RepeatSubmit(expireSeconds = 8)
    public ResponseMessage massagistEvaluate(@Validated @RequestBody MassagistEvaluateAddCommand command) {
        if (memberMyApplicationService.addMyEvaluate(command) == true) return responseHelper.success();
        return responseHelper.fail();
    }

}
